<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas图片简单处理</title>
</head>

<body>
  <div>
    <button onclick="onMosaic()" style="background-color: lightgreen;">马赛克/去马赛克</button>
    <button onclick="onPartMosaic()" style="background-color: yellow;">局部马赛克</button>
  </div>
  <canvas id="cvs"></canvas>
</body>
<script>
  const cvs = document.querySelector('#cvs')
  const ctx = cvs.getContext('2d')
  const img = new Image()
  //相当于用js获取img
  img.src = './keli.jpg'
  img.onload = () => {
    cvs.width = img.width / 2
    cvs.height = img.height / 2
    //画布坐标是马赛克中心点
    ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
    //画布内容初始化
  }
  let isMosaic = false
  // 马赛克
  function onMosaic() {
    // 马赛克比例
    const bl = 20
    if (isMosaic) {
      isMosaic = false
      return ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
    }
    isMosaic = true
    const imgData = ctx.getImageData(0, 0, cvs.width, cvs.height)
    const data = imgData.data
    //data 内容是img的rgb值
    //console.log(data)
    for (let i = 0; i < data.length; i += 4 * bl) {
      for (let b = 0; b < bl; b++) {
        data[i + b * 4] = data[i]
        data[i + 1 + b * 4] = data[i + 1]
        data[i + 2 + b * 4] = data[i + 2]
        data[i + 3 + b * 4] = data[i + 3]
        //4为rgba共有四个数值组成
        //右边为img 的rgb的颜色信息
        //内层循环，将方圆20px（x轴）的rgb颜色信息都设置为一样的
      }
    }
    ctx.putImageData(imgData, 0, 0)
  }
  // 局部马赛克
  function onPartMosaic() {
    // 马赛克比例
    const bl = 20
    // 马赛克区域
    const parts = [
      {
        partX: 100,
        partY: 270,
        partWidth: 350,
        partHeight: 600
      }
    ]

    if (isMosaic) {
      isMosaic = false
      return ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
    }
    isMosaic = true
    const imgData = ctx.getImageData(0, 0, cvs.width, cvs.height)
    const data = imgData.data
    for (let i = 0; i < data.length; i += 4 * bl) {
      const x = (i / 4) % cvs.width
      const y = parseInt((i / 4) / cvs.width)
      //每个像素点的x，y坐标
      // 有一个返回true，则result为true
      const result = parts.some(v => {
        return x >= v.partX && x <= v.partX + v.partWidth && y >= v.partY && y <= v.partY + v.partHeight
      })
      if (result) {
        for (let b = 0; b < bl; b++) {
          data[i + b * 4] = data[i]
          data[i + 1 + b * 4] = data[i + 1]
          data[i + 2 + b * 4] = data[i + 2]
          data[i + 3 + b * 4] = data[i + 3]
        }
      }
    }
    ctx.putImageData(imgData, 0, 0)
  }
</script>

</html>